home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / What's New? / Software Development Kits / Mac OS USB DDK / MacOS USB DDK 1.0b4 / NeptuneDDK / Examples / SerialBox / serialbox.c next >
Encoding:
C/C++ Source or Header  |  1998-06-26  |  23.0 KB  |  925 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        serialbox.c
  3.  
  4.     Contains:    Code for serial box driver
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12.  
  13.  
  14. #define PBVERSION1 1
  15. #include <USB.h>
  16.  
  17. #include "DriverServices.h"
  18. #include "processes.h"
  19. #include "ShimSerialInternal.h"
  20. #include "SerialBox.h"
  21.  
  22.  
  23. enum{
  24.     kSerBoxSetBaudRate = 0,
  25.     kSerBoxSetStopBits = 1,
  26.     kSerBoxSetDataBits = 2,
  27.     kSerBoxSetParity = 3,
  28.     kSerBoxSetDTRState = 0xa,
  29.     kSerBoxSetRTSState = 0xb,
  30.     kSerBoxSetBreakState = 0xc,
  31.     kSerBoxSetControl = 0x10,
  32.     kSerBoxSetParChar = 0x11,
  33.     kSerBoxSetSerNum = 0x20,
  34.     kSerBoxSetStrings = 0x21,
  35.     kSerBoxGetCaps = 0x80,
  36.     kAvailableStatus = 'okok'
  37.     };
  38.  
  39.  
  40. typedef struct{
  41.     USBPB                         pb;
  42.     UInt8                         *errorString;
  43.     USBConfigurationDescriptor     *conf;
  44.     USBInterfaceDescriptor         *interface;
  45.     UInt32                         interfaceOffset;
  46.     USBDeviceRef                 deviceRef;
  47.     USBPipeRef                     bulkIn;
  48.     USBPipeRef                     bulkOut;
  49.     USBPipeRef                     interrupt;
  50.     USBDeviceDescriptorPtr        deviceDescriptor;
  51.     UInt8                        modemStatus;
  52.     UInt8                        lineStatus;
  53.     UInt8                         onError;
  54.     UInt8                         retries;
  55.     }serBoxPB;
  56.  
  57. static serBoxPB     gSerialGlobals;
  58. static USBPB        syncPB, interruptPB, readPB, writePB;
  59.  
  60.  
  61. #if 1
  62.  
  63.     /* Incorporate debugging strings */
  64. #define noteError(s)    sp->errorString = s;
  65.  
  66. #else
  67.  
  68.     /* eliminate Error strings */
  69. #define noteError(s)
  70.  
  71. #endif
  72.  
  73.  
  74. void serialBoxEntry(USBDeviceRef device, USBDeviceDescriptor *desc);
  75. static void StartStatusMonitor(USBPipeRef interruptPipe);
  76. static void InitializePB(USBPB *pb, USBDeviceRef ref, USBCompletion handler);
  77. void USBStartReadPolling(void);
  78.  
  79. static Boolean immediateError(OSStatus err)
  80. {
  81.     return((err != kUSBPending) && (err != noErr) );
  82. }
  83.  
  84.  
  85. #define buffsize 30
  86.  
  87.  
  88. static void ConfigurationHandler(USBPB *pb)
  89. {
  90. serBoxPB                 *sp = &gSerialGlobals;
  91. USBEndPointDescriptor     *eDesc;
  92. static unsigned char     *aString = "\pA test String";
  93. static unsigned char     buffer[buffsize];
  94. OSStatus                err;
  95.  
  96.     if(pb->usbStatus != noErr)
  97.     {
  98.         if( (sp->onError == 0) && (sp->retries > 0) )
  99.         {
  100.             /* no idea what to do now?? */
  101.             USBExpertFatalError(sp->deviceRef, pb->usbStatus, sp->errorString, 1);
  102.             
  103.             /* Mark port as errored */
  104.         }
  105.         else
  106.         {
  107.             USBExpertStatus(sp->deviceRef, sp->errorString, 2);
  108.             pb->usbRefcon = sp->onError;
  109.  
  110.             /* we'll delay coming back to here */
  111.             sp->retries--;
  112.  
  113.             pb->usbReqCount = 0;
  114.             /* pb->usbFlags = kUSBtaskTime */
  115.             USBDelay(pb);
  116.  
  117.         }
  118.         
  119.         return;
  120.     }
  121.  
  122.     sp->onError = 0;
  123.     
  124. //    USBExpertFatalError(sp->deviceRef, pb->usbStatus, "\pSerialBox: Entering this state", pb->usbRefcon);
  125.  
  126.     do{switch(pb->usbRefcon++)
  127.     {
  128.  
  129.         case 1:
  130.             noteError("\pSerialBox driver does not recognize device (we'll try config 1 anyway)");            
  131.             if(sp->deviceDescriptor->numConf != 1)
  132.             {
  133.                 USBExpertFatalError(sp->deviceRef, kUSBUnknownDeviceErr, sp->errorString, 0);
  134.                 // break;    /* Now what ?? */
  135.             }
  136.             
  137.             /* Configure device to single configuration */
  138.             pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBStandard, kUSBDevice);            
  139.             
  140.             pb->usbBRequest = kUSBRqSetConfig;
  141.             pb->usbWValue = 1; /* Standard only (1st) configuration */
  142. //            pb->usbWValue = 2; /* for USR Modem */
  143.             pb->usbWIndex = 0;
  144.             pb->usbReqCount = 0;
  145.             pb->usbBuffer = nil;
  146.             sp->onError = 1;
  147.  
  148.             noteError("\pSerial Driver Setting Config");            
  149.             if(immediateError(err = USBDeviceRequest(pb)))
  150.             {
  151.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  152.             }        
  153.         break;
  154.  
  155.         case 2:
  156.             /* get the full config descriptor */
  157.             pb->pbVersion = kUSBCurrentPBVersion;
  158.             sp->onError = 1;
  159.             noteError("\pSerial Driver getting full config descriptor");            
  160.             if(immediateError(err = USBGetFullConfigurationDescriptor(pb)))
  161.             {
  162.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  163.             }
  164.         
  165.         break;
  166.  
  167.         case 3:
  168.             /* remember the full config descriptor */
  169.             sp->conf = pb->usbBuffer;
  170.             
  171.             /* find the interface */
  172.             pb->usbReqCount = 0;
  173.             pb->usbValue1 = 0;        /* any class */
  174. //            pb->usbValue1 = kUSBDataClass;        /* any class */
  175.             pb->usbValue2 = 0;        /* any subclass */
  176.             pb->usbValue3 = 0;        /* any protocol */
  177.             pb->usbWValue = 0;        /* alt */
  178.             sp->onError = 1;
  179.             
  180.             noteError("\pSerial Driver parsing the interface");            
  181.             if(immediateError(err = USBFindNextInterfaceDescriptorImmediate(pb)))
  182.             {    /* this should return immediately */
  183.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  184.             }
  185.             
  186.             /* remember the current position */
  187.             sp->interface = pb->usbBuffer;
  188.             sp->interfaceOffset = pb->usbReqCount;
  189.             
  190.             /* Find the out endpoint */
  191.             pb->usbFlags = kUSBOut;
  192.             pb->usbValue1 = kUSBBulk;
  193.             pb->usbValue2 = 0;            /* Find the first one */
  194.             
  195.             noteError("\pSerial Driver parsing the bulk out endpoint");            
  196.             if(immediateError(err = USBFindNextEndpointDescriptorImmediate(pb)))
  197.             {    /* this should return immediately */
  198.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  199.             }
  200.             
  201.             /* Save away the device ref, it gets overwritten by the open */
  202.             sp->deviceRef = pb->usbReference;
  203.             
  204.             pb->usbFlags = kUSBOut;
  205.             /* The params are set up correctly so open it */
  206.             //eDesc = pb->usbBuffer;
  207.             //pb->usbValue = USBToHostWord(eDesc->maxPacketSize);
  208.             // max packet size is now returned in usbValue
  209.             
  210.             noteError("\pSerial Driver opening bulk out pipe");            
  211.             if(immediateError(err = USBOpenPipe(pb)))
  212.             {
  213.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  214.             }        
  215.             
  216.             
  217.         break;
  218.     
  219.         case 4:
  220.             /* Out Endpoint is open */
  221.  
  222.             /* remember the ref */
  223.             sp->bulkOut = pb->usbReference;
  224.             
  225.             /* Find the in endpoint */
  226.  
  227.             /* restore the device ref, it gets overwritten by the open */
  228.             pb->usbReference = sp->deviceRef;
  229.             
  230.             /* set search back to just found interface */
  231.             pb->usbBuffer = sp->interface;
  232.             pb->usbReqCount = sp->interfaceOffset;
  233.             
  234.             pb->usbFlags = kUSBIn;
  235.             pb->usbValue1 = kUSBBulk;
  236.             pb->usbValue2 = 0;            /* Find the first one */
  237.             sp->onError = 1;
  238.             
  239.             noteError("\pSerial Driver parsing the bulk in endpoint");            
  240.             if(immediateError(err = USBFindNextEndpointDescriptorImmediate(pb)))
  241.             {    /* this should return immediatly */
  242.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  243.             }
  244.             
  245.             pb->usbFlags = kUSBIn;
  246.             /* The params are set up correctly so open it */
  247.             eDesc = pb->usbBuffer;
  248.             pb->usbValue3 = USBToHostWord(eDesc->maxPacketSize);
  249.  
  250.             noteError("\pSerial Driver opening bulk in pipe");            
  251.             if(immediateError(err = USBOpenPipe(pb)))
  252.             {
  253.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  254.             }        
  255.             
  256.             
  257.         break;
  258.     
  259.         case 5:
  260.             /* In Endpoint is open */
  261.  
  262.             /* remember the ref */
  263.             sp->bulkIn = pb->usbReference;
  264.             
  265.             /* Find the interrupt endpoint */
  266.  
  267.             /* restore the device ref, it gets overwritten by the open */
  268.             pb->usbReference = sp->deviceRef;
  269.             
  270.             /* set search back to just found interface */
  271.             pb->usbBuffer = sp->interface;
  272.             pb->usbReqCount = sp->interfaceOffset;
  273.             
  274.             pb->usbFlags = kUSBIn;
  275.             pb->usbValue1 = kUSBInterrupt;
  276.             pb->usbValue2 = 0;            /* Find the first one */
  277.             sp->onError = 1;
  278.             
  279.             noteError("\pSerial Driver parsing the interrupt in endpoint");            
  280.             if(immediateError(err = USBFindNextEndpointDescriptorImmediate(pb)))
  281.             {    /* this should return immediatly */
  282.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  283.             }
  284.             
  285.             pb->usbFlags = kUSBIn;
  286.             /* The params are set up correctly so open it */
  287.             eDesc = pb->usbBuffer;
  288.             pb->usbValue3 = USBToHostWord(eDesc->maxPacketSize);
  289.  
  290.             noteError("\pSerial Driver opening interrupt in pipe");            
  291.             if(immediateError(err = USBOpenPipe(pb)))
  292.             {
  293.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  294.             }        
  295.             
  296.             
  297.         break;
  298.  
  299.         case 6:
  300.             /* Interrupt is open */
  301.  
  302.             /* remember the ref */
  303.             sp->interrupt = pb->usbReference;
  304.             
  305.             StartStatusMonitor(sp->interrupt);
  306.             
  307.             // device is fully configured, ready for somebody to set the baud rate, etc.
  308.             // and start reading/writing to the bulk endpoints
  309.             syncPB.usbStatus = kAvailableStatus;
  310.             USBExpertStatus(sp->deviceRef, "\pSerial Box configuration complete.", 0);
  311.         break;
  312.     
  313.         default:
  314.             noteError("\pInternal Error unused case in SerialBox handler");            
  315.             USBExpertFatalError(sp->deviceRef, kUSBInternalErr, sp->errorString, pb->usbRefcon);
  316.         break;
  317.     }
  318.     break;    /* only execute once, unless continue used */
  319.     }while(1);    /* so case can be reentered with a continue */
  320. }
  321.  
  322. UInt32    statusData;
  323.  
  324. static void ResetInterruptPB(USBPB *pb)
  325. {
  326.     pb->usbReqCount = 4;
  327.     pb->usbBuffer = &statusData;
  328.     pb->usbStatus = noErr;
  329. }
  330.  
  331. static void interruptCompletion(USBPB *pb)
  332. {
  333.     serBoxPB     *sp = &gSerialGlobals;
  334.     OSStatus    err;
  335.  
  336.     if (pb->usbStatus != noErr){
  337.         USBClearPipeStallByReference(gSerialGlobals.interrupt);
  338.         USBExpertFatalError(sp->deviceRef, pb->usbStatus, "\pSerialDriver: interruptCompletion err, clearing stall", 0);
  339.     } else {
  340.         sp->modemStatus = statusData & 0x0FF;
  341.         sp->lineStatus = (statusData >> 8) & 0x0FF;
  342.     }
  343.         
  344.     ResetInterruptPB(pb);
  345.  
  346.     if(immediateError(err = USBIntRead(pb)))
  347.     {
  348.         USBExpertFatalError(sp->deviceRef, err, "\pCouldn't queue interrupt read!", 0);
  349.     }        
  350.         
  351. }
  352.  
  353. static void StartStatusMonitor(USBPipeRef interruptPipe)
  354. {
  355.     USBPB        *pb = &interruptPB;
  356.     serBoxPB     *sp = &gSerialGlobals;
  357.     OSStatus    err;
  358.     
  359.     InitializePB(pb, interruptPipe, interruptCompletion);
  360.  
  361.     ResetInterruptPB(pb);
  362.  
  363.     if(immediateError(err = USBIntRead(pb)))
  364.     {
  365.         USBExpertFatalError(sp->deviceRef, err, "\pCouldn't start interrupt read!", 0);
  366.     }        
  367.  
  368. }
  369.  
  370.  
  371. // Synchronous routines for setting UART parameters
  372.  
  373. static void syncCompletion(USBPB *pb)
  374. {
  375.     serBoxPB     *sp = &gSerialGlobals;
  376.  
  377.     if (pb->usbStatus != noErr)
  378.         USBExpertFatalError(sp->deviceRef, pb->usbStatus, "\pSerialDriver: syncCompletion err for bRequest", pb->usbBRequest);
  379.         
  380.     pb->usbStatus = kAvailableStatus;
  381. }
  382.  
  383. Boolean TimeoutPreviousRequest(void)
  384. {
  385.     USBPB        *pb = &syncPB;
  386.     serBoxPB     *sp = &gSerialGlobals;
  387.     AbsoluteTime    startTime;
  388.     Duration        elapsedTime;
  389.  
  390.     if (pb->usbStatus == kAvailableStatus)
  391.         return(false);
  392.     
  393.     startTime = UpTime();
  394.  
  395.     while (pb->usbStatus != kAvailableStatus){
  396.         elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
  397.         if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000);      // make sure it's in milliseconds
  398.         if (elapsedTime > 100*durationMillisecond){
  399.             USBExpertFatalError(sp->deviceRef, -1, "\pSerial Driver, device request timeout - aborting", 0);
  400.             USBAbortPipeByReference(pb->usbReference);
  401.             return(true);
  402.         }
  403.     }
  404.     return (false);
  405. }
  406.  
  407. void USBSetBaudRateDivisor(UInt16 divisor)
  408. {
  409.     USBPB        *pb = &syncPB;
  410.     serBoxPB     *sp = &gSerialGlobals;
  411.     OSStatus     err;
  412.  
  413.     if (TimeoutPreviousRequest())
  414.         return;
  415.  
  416.     pb->usbStatus = noErr;
  417.     pb->pbVersion = kUSBCurrentPBVersion;
  418.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);            
  419.     
  420.     pb->usbBRequest = kSerBoxSetBaudRate;
  421.     pb->usbWValue = divisor; 
  422.     pb->usbWIndex = 0;         /* UART, we only have the one */
  423.     pb->usbReqCount = 0;
  424.  
  425.     if(immediateError(err = USBDeviceRequest(pb)))
  426.     {
  427.         USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting Baud rate", 0);
  428.         pb->usbStatus = kAvailableStatus;
  429.     }
  430. }
  431. void USBSetParChar(UInt8 parChar)
  432. {
  433.     USBPB        *pb = &syncPB;
  434.     serBoxPB     *sp = &gSerialGlobals;
  435.     OSStatus     err;
  436.  
  437.     if (TimeoutPreviousRequest())
  438.         return;
  439.  
  440.     pb->usbStatus = noErr;
  441.     pb->pbVersion = kUSBCurrentPBVersion;
  442.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);            
  443.     
  444.     pb->usbBRequest = kSerBoxSetParChar;
  445.     pb->usbWValue = parChar; 
  446.     pb->usbWIndex = 0;         /* UART, we only have the one */
  447.     pb->usbReqCount = 0;
  448.  
  449.     if(immediateError(err = USBDeviceRequest(pb)))
  450.     {
  451.         USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting Baud rate", 0);
  452.         pb->usbStatus = kAvailableStatus;
  453.     }
  454. }
  455. void USBSetStopBits(UInt16 stopBits)
  456. {
  457.     USBPB        *pb = &syncPB;
  458.     serBoxPB     *sp = &gSerialGlobals;
  459.     OSStatus     err;
  460.  
  461.     if (TimeoutPreviousRequest())
  462.         return;
  463.  
  464.     pb->usbStatus = noErr;
  465.     pb->pbVersion = kUSBCurrentPBVersion;
  466.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);            
  467.     
  468.     pb->usbBRequest = kSerBoxSetStopBits;
  469.     pb->usbWValue = stopBits; 
  470.     pb->usbWIndex = 0;         /* UART, we only have the one */
  471.     pb->usbReqCount = 0;
  472.  
  473.     if(immediateError(err = USBDeviceRequest(pb)))
  474.     {
  475.         USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting StopBits", 0);
  476.         pb->usbStatus = kAvailableStatus;
  477.     }
  478. }
  479. void USBSetDataBits(UInt16 dataBits)
  480. {
  481.     USBPB        *pb = &syncPB;
  482.     serBoxPB     *sp = &gSerialGlobals;
  483.     OSStatus     err;
  484.  
  485.     if (TimeoutPreviousRequest())
  486.         return;
  487.  
  488.     pb->usbStatus = noErr;
  489.     pb->pbVersion = kUSBCurrentPBVersion;
  490.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);            
  491.     
  492.     pb->usbBRequest = kSerBoxSetDataBits;
  493.     pb->usbWValue = dataBits; 
  494.     pb->usbWIndex = 0;         /* UART, we only have the one */
  495.     pb->usbReqCount = 0;
  496.  
  497.     if(immediateError(err = USBDeviceRequest(pb)))
  498.     {
  499.         USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting dataBits", 0);
  500.         pb->usbStatus = kAvailableStatus;
  501.     }
  502. }
  503. void USBSetParityBits(UInt16 parityBits)
  504. {
  505.     USBPB        *pb = &syncPB;
  506.     serBoxPB     *sp = &gSerialGlobals;
  507.     OSStatus     err;
  508.  
  509.     if (TimeoutPreviousRequest())
  510.         return;
  511.  
  512.     pb->usbStatus = noErr;
  513.     pb->pbVersion = kUSBCurrentPBVersion;
  514.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);            
  515.     
  516.     pb->usbBRequest = kSerBoxSetParity;
  517.     pb->usbWValue = parityBits; 
  518.     pb->usbWIndex = 0;         /* UART, we only have the one */
  519.     pb->usbReqCount = 0;
  520.  
  521.     if(immediateError(err = USBDeviceRequest(pb)))
  522.     {
  523.         USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting parity", 0);
  524.         pb->usbStatus = kAvailableStatus;
  525.     }
  526. }
  527. void USBSetControl(UInt16 state)
  528. {
  529.     USBPB        *pb = &syncPB;
  530.     serBoxPB     *sp = &gSerialGlobals;
  531.     OSStatus     err;
  532.  
  533.     if (TimeoutPreviousRequest())
  534.         return;
  535.  
  536.     pb->usbStatus = noErr;
  537.     pb->pbVersion = kUSBCurrentPBVersion;
  538.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);            
  539.     
  540.     pb->usbBRequest = kSerBoxSetControl;
  541.     pb->usbWValue = state; 
  542.     pb->usbWIndex = 0;         /* UART, we only have the one */
  543.     pb->usbReqCount = 0;
  544.  
  545.     if(immediateError(err = USBDeviceRequest(pb)))
  546.     {
  547.         USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting Control", 0);
  548.         pb->usbStatus = kAvailableStatus;
  549.     }
  550. }
  551.  
  552. void USBSetDTRState(Boolean state)
  553. {
  554.     USBPB        *pb = &syncPB;
  555.     serBoxPB     *sp = &gSerialGlobals;
  556.     OSStatus     err;
  557.  
  558.     if (TimeoutPreviousRequest())
  559.         return;
  560.  
  561.     pb->usbStatus = noErr;
  562.     pb->pbVersion = kUSBCurrentPBVersion;
  563.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);            
  564.     
  565.     pb->usbBRequest = kSerBoxSetDTRState;
  566.     pb->usbWValue = state; 
  567.     pb->usbWIndex = 0;         /* UART, we only have the one */
  568.     pb->usbReqCount = 0;
  569.  
  570.     if(immediateError(err = USBDeviceRequest(pb)))
  571.     {
  572.         USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting DTR State", 0);
  573.         pb->usbStatus = kAvailableStatus;
  574.     }
  575. }
  576. void USBSetRTSState(Boolean state)
  577. {
  578.     USBPB        *pb = &syncPB;
  579.     serBoxPB     *sp = &gSerialGlobals;
  580.     OSStatus     err;
  581.  
  582.     if (TimeoutPreviousRequest())
  583.         return;
  584.  
  585.     pb->usbStatus = noErr;
  586.     pb->pbVersion = kUSBCurrentPBVersion;
  587.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);            
  588.     
  589.     pb->usbBRequest = kSerBoxSetRTSState;
  590.     pb->usbWValue = state; 
  591.     pb->usbWIndex = 0;         /* UART, we only have the one */
  592.     pb->usbReqCount = 0;
  593.  
  594.     if(immediateError(err = USBDeviceRequest(pb)))
  595.     {
  596.         USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting RTS State", 0);
  597.         pb->usbStatus = kAvailableStatus;
  598.     }
  599. }
  600. void USBSetBreakState(Boolean state)
  601. {
  602.     USBPB        *pb = &syncPB;
  603.     serBoxPB     *sp = &gSerialGlobals;
  604.     OSStatus     err;
  605.  
  606.     if (TimeoutPreviousRequest())
  607.         return;
  608.  
  609.     pb->usbStatus = noErr;
  610.     pb->pbVersion = kUSBCurrentPBVersion;
  611.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);            
  612.     
  613.     pb->usbBRequest = kSerBoxSetBreakState;
  614.     pb->usbWValue = state; 
  615.     pb->usbWIndex = 0;         /* UART, we only have the one */
  616.     pb->usbReqCount = 0;
  617.  
  618.     if(immediateError(err = USBDeviceRequest(pb)))
  619.     {
  620.         USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting Break State", 0);
  621.         pb->usbStatus = kAvailableStatus;
  622.     }
  623. }
  624. UInt32    USBGetModemStatus(void)
  625. {
  626.     serBoxPB     *sp = &gSerialGlobals;
  627.  
  628.     return(sp->modemStatus);
  629. }
  630.  
  631. void serialBoxEntry(USBDeviceRef device, USBDeviceDescriptor *desc)
  632. {
  633. static Boolean                 beenThereDoneThat = false;
  634. static USBDeviceDescriptor     ourDeviceDescriptor;
  635.  
  636.     if(beenThereDoneThat)
  637.     {
  638.         USBExpertFatalError(device, kUSBInternalErr, "\pSerial driver called second time", 0);
  639.         return;
  640.     }
  641.     beenThereDoneThat = true;
  642.     
  643.     ourDeviceDescriptor = *desc;
  644.     gSerialGlobals.deviceDescriptor = &ourDeviceDescriptor;
  645.     gSerialGlobals.deviceRef = device;
  646.     
  647.     InitializePB(&syncPB, device, syncCompletion);
  648.  
  649.     InitializePB(&gSerialGlobals.pb, device, ConfigurationHandler);
  650.     gSerialGlobals.pb.usbRefcon = 1;
  651.     gSerialGlobals.pb.usbBuffer = nil;
  652.  
  653.     ConfigurationHandler(&gSerialGlobals.pb);
  654. }
  655.  
  656.  
  657. static void InitializePB(USBPB *pb, USBDeviceRef ref, USBCompletion handler)
  658. {
  659.     pb->pbVersion = kUSBCurrentPBVersion;
  660.     pb->pbLength = sizeof(*pb);
  661.     pb->usbReference = ref;
  662.     pb->usbCompletion = handler;
  663.     pb->usbStatus = noErr;
  664.     
  665. }
  666.  
  667. void ShimInput(UInt8 *buf, UInt32 count)
  668. {
  669.     IOParam *                        pb;
  670.     OSErr                            result;
  671.     register UInt16                    nextIndex;
  672.     register unsigned char            rcvByte;
  673.     unsigned char                    lineStatus;
  674.     unsigned char                    newErrs;
  675.     unsigned char                    cumErrs;
  676.     ShimSerialGlobals *                globals = gGlobals;
  677.     
  678.         
  679.     //    set return result to incomplete
  680.  
  681.     result = 1;
  682.     cumErrs = 0;
  683.  
  684.     while(count--)
  685.     {
  686.         //    pull out uart line status
  687.     
  688.         lineStatus = 0 /* gSerialGlobals.lineStatus */;
  689.  
  690.         //  handle reading of data available in the uart receive buffer
  691.         
  692.         rcvByte = *buf++;
  693.         
  694.         //    if software output flow control is enabled, check if this is an xon or xoff character
  695.         
  696.         if (    globals->serShk.fXOn && 
  697.                 (!(lineStatus & kRxErrMask)) &&
  698.                 (    (rcvByte == globals->serShk.xOn) || 
  699.                     (rcvByte == globals->serShk.xOff)))
  700.         {
  701.  
  702.             //    set software output flow control based on xon or xoff received
  703.  
  704.             globals->serStat.xOffHold = (rcvByte == globals->serShk.xOff);
  705.             B_EnableOutput(globals);
  706.         }
  707.         else
  708.         {
  709.             //    else this is to be treated as a data byte for the client
  710.             
  711.             //    compute index into our input buffer
  712.  
  713.             nextIndex = globals->inBufEndIndex + 1;
  714.             if ( nextIndex >= globals->inBufLen ) 
  715.                 nextIndex = 0;
  716.             
  717.             //    stuff the character into the input buffer and update the index
  718.  
  719.             globals->inBufPtr[globals->inBufEndIndex] = rcvByte;
  720.             globals->inBufEndIndex = nextIndex;
  721.  
  722.             //    check for input buffer overflow
  723.  
  724.             if ( globals->inBufEndIndex == globals->inBufStartIndex )
  725.             {
  726.                 //    mark that we've had an overrun
  727.  
  728.                 globals->serStat.cumErrs |= swOverrunErr;
  729.                 cumErrs |= swOverrunErr;
  730.                 
  731.                 //    drop oldest character from our internal buffer
  732.  
  733.                 globals->inBufStartIndex++;
  734.                 if ( globals->inBufStartIndex >= globals->inBufLen )
  735.                     globals->inBufStartIndex = 0;
  736.                 
  737.                 //    we've had a software overrun -- rather than empty the uart
  738.                 //    fifo and overwrite up to 16 bytes, we quit now and let the
  739.                 //    client get a chance to read in the existing bytes -- if there
  740.                 //    are still bytes pending in the fifo, we'll get interrupted
  741.                 //    again real soon now...
  742.             }
  743.         }
  744.  
  745.         //    check for receive error condition
  746.         //    for case of kRxStatusInterrupt with no data available
  747.     
  748.         if ( lineStatus & kRxErrMask )
  749.         {
  750.             //    mark error
  751.     
  752.             newErrs = 0;
  753.             if ( lineStatus & kParityErr )         newErrs |= parityErr;
  754.             if ( lineStatus & kOverrunErr )     newErrs |= hwOverrunErr;
  755.             if ( lineStatus & kFramingErr )     newErrs |= framingErr;
  756.             if ( lineStatus & kBreakDetect )     newErrs |= breakErr;
  757.             globals->serStat.cumErrs |= newErrs;
  758.             cumErrs |= newErrs;
  759.         }
  760.         
  761.         //    check for an outstanding read request
  762.         
  763.         pb = (IOParam *)globals->pbIn;
  764.         if (pb)
  765.         {
  766.             //    copy bytes from input buffer into pb read buffer
  767.             //    (result is either 1=incomplete or 0=complete)
  768.     
  769.             result = B_FillReadRequest(globals, pb);
  770.             
  771.             //    handle errors that cause read aborts
  772.             
  773.             if ( cumErrs & globals->serShk.errs ) 
  774.                 result = rcvrErr;
  775.             
  776.             //    if we have fulfilled this read request, we
  777.             //  need to call IOCommandIsComplete and on it
  778.             //  and continue processing with the next request
  779.             
  780.             if ( result <= noErr )
  781.             {
  782.                 globals->pbIn = nil;
  783.                 break;
  784.             }
  785.         }
  786.         
  787.         
  788.         //    handle hardware (dtr or rts) or software
  789.         //    (xon / xoff) input flow control as necessary
  790.         
  791.         B_InputFlowControl(globals);
  792.         
  793.     }
  794.     
  795.     // clean up after ourselves
  796.     if (result <= noErr)
  797.         ShimSerialStubIODone((union ParamBlockRec *)pb,*(globals->dceIn),result);
  798. }
  799.  
  800. static errCount, readActive = false;
  801.  
  802. void readCompletion(USBPB *pb)
  803. {
  804.     if (pb->usbStatus == noErr){
  805.         ShimInput(pb->usbBuffer, pb->usbActCount);
  806.     }else{
  807.         USBClearPipeStallByReference(gSerialGlobals.bulkIn);
  808.         if (pb->usbActCount > 0)
  809.             ShimInput(pb->usbBuffer, pb->usbActCount);
  810.             
  811.         if ((pb->usbStatus != kUSBUnderRunErr) && errCount++ < 10)
  812.             USBExpertFatalError(gSerialGlobals.deviceRef, pb->usbStatus, "\pRead completion error, actCount", pb->usbActCount);
  813.     }
  814.     readActive = false;
  815.     if (pb->usbStatus != kUSBAbortedError)    // are we being asked to quit?
  816.         USBStartReadPolling();
  817.         
  818. }
  819.  
  820. static UInt8    ioBuffer[64];
  821.  
  822. void USBStartReadPolling()
  823. {
  824.     OSStatus status;
  825.     
  826.     if (gSerialGlobals.bulkIn && !readActive){
  827.         InitializePB(&readPB, gSerialGlobals.bulkIn, readCompletion);
  828.         readPB.usbBuffer = ioBuffer;
  829.         readPB.usbReqCount = sizeof(ioBuffer);
  830.         if(immediateError(status = USBBulkRead(&readPB)))
  831.         {
  832.             USBExpertFatalError(gSerialGlobals.deviceRef, status, "\pSerial: Couldn't start read polling", 0);
  833.         }
  834.         readActive = true;
  835.     }
  836. }
  837.  
  838. void USBStopReadPolling()
  839. {
  840.     USBExpertStatus(gSerialGlobals.deviceRef, "\pAborting Bulk-in pipe", 0);
  841.  
  842.     if (gSerialGlobals.bulkIn){
  843.         USBAbortPipeByReference(gSerialGlobals.bulkIn);
  844.     }
  845. }
  846.  
  847.  
  848. static    UInt32        writeActive;
  849.  
  850. void writeCompletion(USBPB *pb)
  851. {
  852.     IOParam *iopb;
  853.     
  854.     writeActive--;
  855.     if (pb->usbStatus != noErr) {
  856.         USBClearPipeStallByReference(pb->usbReference);
  857.         USBExpertFatalError(gSerialGlobals.deviceRef, pb->usbStatus, "\pWrite Failed", pb->usbActCount);
  858.     }
  859.     
  860.     iopb = (IOParam *)pb->usbRefcon;
  861.     
  862.     iopb->ioActCount = pb->usbActCount;
  863.     
  864.     ShimSerialStubIODone((union ParamBlockRec *)iopb, *(gGlobals->dceOut), pb->usbStatus ? ioErr : 0);
  865.  
  866. }
  867.  
  868. OSStatus USBSerialWrite(IOParam *pb)
  869. {
  870.     OSStatus     status = noErr;
  871.     
  872.     if (writeActive){
  873.         USBExpertFatalError(gSerialGlobals.deviceRef, writePB.usbStatus, "\pOverlapping writes!", pb->ioReqCount);
  874.         status = ioErr;
  875.     } else if (gSerialGlobals.bulkOut){
  876.         
  877.         InitializePB(&writePB, gSerialGlobals.bulkOut, writeCompletion);
  878.         writePB.usbRefcon = (UInt32)pb;
  879.         writePB.usbBuffer = pb->ioBuffer;
  880.         writePB.usbReqCount = pb->ioReqCount;
  881.         if(immediateError(status = USBBulkWrite(&writePB)))
  882.         {
  883.             USBExpertFatalError(gSerialGlobals.deviceRef, status, "\pSerial: Couldn't start write", 0);
  884.         } else {
  885.             writeActive++;
  886.             status = 1;
  887.         }
  888.     } else {
  889.         status = ioErr;
  890.     }
  891.     return (status);
  892. }
  893.  
  894. void KillUSBIO(void)
  895. {
  896.     IOParam *                        pb;
  897.     ShimSerialGlobals *                globals = gGlobals;
  898.  
  899.     USBExpertStatus(gSerialGlobals.deviceRef, "\pSerial Box: Killing all USB IO", 0);
  900.  
  901.     if (gSerialGlobals.bulkIn){
  902.         USBAbortPipeByReference(gSerialGlobals.bulkIn);
  903.         gSerialGlobals.bulkIn = nil;
  904.     }
  905.     if (gSerialGlobals.bulkOut){
  906.         USBAbortPipeByReference(gSerialGlobals.bulkOut);
  907.         gSerialGlobals.bulkOut = nil;
  908.     }
  909.     if (gSerialGlobals.interrupt){
  910.         USBAbortPipeByReference(gSerialGlobals.interrupt);
  911.         gSerialGlobals.interrupt = nil;
  912.     }
  913.  
  914.     pb = (IOParam *)globals->pbIn;
  915.     if (pb) {
  916.         ShimSerialStubIODone((union ParamBlockRec *)pb,*(globals->dceIn),ioErr);
  917.     }
  918.     pb = (IOParam *)globals->pbOut;
  919.     if (pb) {
  920.         ShimSerialStubIODone((union ParamBlockRec *)pb,*(globals->dceOut),ioErr);
  921.     }
  922. }
  923.  
  924.  
  925.